<?php

include ("Node.php");

class Graph {
	var $nodes;
	var $id_generator;
	var $clones;
	
	public function __construct () {
		$this->id_generator = 0;
		$this->nodes = array();
	}
	
	public function descrease_local_error($bt){
		for ($i = 0; $i < count($this->nodes); $i++){
			$this->nodes[$i]->error *= $bt;
		}
	}
	
	public function max_local_error (){
		$pos = 0; 
		$max = $this->nodes[0]->error;
		for ($i = 1; $i < count($this->nodes); $i++){
			if ($this->nodes[$i]->error > $max){
				$pos = $i;
				$max = $this->nodes[$i]->error;
			}
		}
		return $this->nodes[$pos]->id;
	}
	
	public function max_local_error_from ($id){
		$pos = $this->__find_position_node($id);
		$iterator = 0;
		$max = $this->nodes[$this->nodes[$pos]->edges[$iterator]->node_id]->error;
		for ($i = 1; $i < count($this->nodes[$pos]->edges); $i++){
			if ($this->nodes[$this->nodes[$pos]->edges[$i]->node_id]->error > $max){
				$iterator = $i;
				$max = $this->nodes[$this->nodes[$pos]->edges[$i]->node_id]->error;
			}
		}
		return $this->nodes[$pos]->edges[$iterator]->node_id;
	}
	
	public function erase_edge($id1, $id2){
	    $n1 = $this->__find_position_node($id1);
	    $n2 = $this->__find_position_node($id2);
		$this->nodes[$n1]->erase_edge($id2);
		$this->nodes[$n2]->erase_edge($id1);
	}
	
	public function increase_local_error ($id, $val) {
		$npos = $this->__find_position_node($id);
		$this->nodes[$npos]->increase_local_error($val);
	}
	
	public function add_node ($val){
		$idt = $this->id_generator;
		$node = new Node($val, $this->id_generator);
		$this->nodes[] = $node;
		$this->id_generator++;
		return $idt;
	}
	
	public function move_to ($id, array $pattern, $eb, $en){
		$pos = $this->__find_position_node($id);
		 $this->nodes[$pos]->move_to($pattern, $eb);
		 for ($i = 0; $i < count($this->nodes[$pos]->edges); $i++){
			$nid = $this->nodes[$pos]->edges[$i]->node_id;
			$npos = $this->__find_position_node($nid);    
			$this->nodes[$npos]->move_to($pattern,$en);
		 }	
	}
	
	public function remove_edges ($limit){
		for ($i = 0; $i < count($this->nodes); $i++){
			$this->nodes[$i]->remove_edges($limit);
			if (count($this->nodes[$i]->edges) ==  0) 
				unset ($this->nodes[$i]); // Posible conflicto en iteracion
        $this->nodes = array_values($this->nodes);   
		}
	}
	
	public function add_edge ($id1, $id2, $w = 0.0){
	    $n1 = $this->__find_position_node($id1);
	    $n2 = $this->__find_position_node($id2);
		$this->nodes[$n1]->add_edge($id2,$w);
		$this->nodes[$n2]->add_edge($id1,$w);
	}
	
	public function reset_edge ($id1, $id2, $w){
	    $n1 = $this->__find_position_node($id1);
	    $n2 = $this->__find_position_node($id2);
		for ($i = 0; $i < count($this->nodes[$n1]->edges); $i++){
			if ($this->nodes[$n1]->edges[$i]->node_id == $n2){
				$this->nodes[$n1]->edges[$i]->weight = $w;
				break;
			}
		}
		for ($i = 0; $i < count($this->nodes[$n2]->edges); $i++){
			if ($this->nodes[$n2]->edges[$i]->node_id == $n1){
				$this->nodes[$n2]->edges[$i]->weight = $w;
				break;
			}
		}
	}
	
	public function increase_edges_ages ($pos) {
		$npos = $this->__find_position_node($pos);
		for ($i = 0; $i < count($this->nodes[$npos]->edges); $i++){
			$this->nodes[$npos]->edges[$i]->weight++;
			$id = $this->nodes[$npos]->edges[$i]->node_id;
			for ($k = 0; $k < count ($this->nodes[$id]->edges); $k++){
				if ($this->nodes[$id]->edges[$k]->node_id == $pos){
					$this->nodes[$id]->edges[$k]->weight ++;
					break;
				}
			}
		}
	}
	
	public function exists_edge ($id1, $id2) {
	    $n1 = $this->__find_position_node($id1);
	    $n2 = $this->__find_position_node($id2);
		$exists = false;
		for ($i = 0; $i < count($this->nodes[$n1]->edges); $i++){
			if ($this->nodes[$n1]->edges[$i]->node_id == $n2)
				$exists = true;
		}
		return $exists;
	}
	
	public function clone_nodes(){
		$this->clones = $this->nodes;
	}
	
	public function find_nearest ($val){
		$iterator = 0;
		$distance = $this->clones[$iterator]->pattern->euclidean_distance($val);
		for ($pos = 1; $pos < count($this->clones); $pos++){
			$ndistance = $this->clones[$pos]->pattern->euclidean_distance($val);
			if ($ndistance < $distance) {
					$iterator = $pos;
					$distance = $ndistance;
			}
		}
	    $res = $this->clones[$iterator]->id;
	    unset ($this->clones[$iterator]);
	    $this->clones = array_values($this->clones);
		return $res;
	}
	
	public function __find_position_node ($n){
		$pos = 0;
		for (; $pos < count($this->nodes); $pos++){
			if ($this->nodes[$pos]->id == $n) break;
		}
		return $pos;
	}
	
	public function printing () {
		for ($i = 0; $i < count ($this->nodes); $i++){
			$this->nodes[$i]->printing();
		}
	}
	
}

?>